home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 1.iso / toolbox / src / demos / OpenGL / tex_cube / tex_cube.c++ < prev    next >
C/C++ Source or Header  |  1996-11-11  |  17KB  |  642 lines

  1. /*
  2.  * (c) Copyright 1993, 1994, Silicon Graphics, Inc.
  3.  * ALL RIGHTS RESERVED
  4.  * Permission to use, copy, modify, and distribute this software for
  5.  * any purpose and without fee is hereby granted, provided that the above
  6.  * copyright notice appear in all copies and that both the copyright notice
  7.  * and this permission notice appear in supporting documentation, and that
  8.  * the name of Silicon Graphics, Inc. not be used in advertising
  9.  * or publicity pertaining to distribution of the software without specific,
  10.  * written prior permission.
  11.  *
  12.  * THE MATERIAL EMBODIED ON THIS SOFTWARE IS PROVIDED TO YOU "AS-IS"
  13.  * AND WITHOUT WARRANTY OF ANY KIND, EXPRESS, IMPLIED OR OTHERWISE,
  14.  * INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY OR
  15.  * FITNESS FOR A PARTICULAR PURPOSE.  IN NO EVENT SHALL SILICON
  16.  * GRAPHICS, INC.  BE LIABLE TO YOU OR ANYONE ELSE FOR ANY DIRECT,
  17.  * SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY
  18.  * KIND, OR ANY DAMAGES WHATSOEVER, INCLUDING WITHOUT LIMITATION,
  19.  * LOSS OF PROFIT, LOSS OF USE, SAVINGS OR REVENUE, OR THE CLAIMS OF
  20.  * THIRD PARTIES, WHETHER OR NOT SILICON GRAPHICS, INC.  HAS BEEN
  21.  * ADVISED OF THE POSSIBILITY OF SUCH LOSS, HOWEVER CAUSED AND ON
  22.  * ANY THEORY OF LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE
  23.  * POSSESSION, USE OR PERFORMANCE OF THIS SOFTWARE.
  24.  *
  25.  * US Government Users Restricted Rights
  26.  * Use, duplication, or disclosure by the Government is subject to
  27.  * restrictions set forth in FAR 52.227.19(c)(2) or subparagraph
  28.  * (c)(1)(ii) of the Rights in Technical Data and Computer Software
  29.  * clause at DFARS 252.227-7013 and/or in similar or successor
  30.  * clauses in the FAR or the DOD or NASA FAR Supplement.
  31.  * Unpublished-- rights reserved under the copyright laws of the
  32.  * United States.  Contractor/manufacturer is Silicon Graphics,
  33.  * Inc., 2011 N.  Shoreline Blvd., Mountain View, CA 94039-7311.
  34.  *
  35.  * OpenGL(TM) is a trademark of Silicon Graphics, Inc.
  36.  */
  37. #include "oglwindow.h"
  38. #include "unitsquare.h"
  39. #include "texture.h"
  40.  
  41. #include <X11/keysym.h>
  42.  
  43. #include <stdlib.h>
  44. #include <string.h>
  45. #include <math.h>
  46. #include <sys/time.h>
  47.  
  48. oglwindow *window;
  49. unitsquare *square;
  50. texture **texmap;
  51.  
  52. GLfloat matrix[16];
  53.  
  54. // Texture map to use by default - very hard-coded
  55. static char default_image[] = "flowers2.rgb";
  56.  
  57. // Font for the initial wait message
  58. const char default_font[] = "-*-helvetica-bold-r-*-*-17-*-*-*-*-*-*-*";
  59.  
  60. int use_texture = 1;        // Use textures?
  61. int n_textures = 1;        // Number of textures
  62. int reload_textures = 0;    // Reload textures?
  63. int cube = 1;            // Draw cube instead of square?
  64. int transparency = 0;        // Has transparency --> multipass?
  65. int immediate = 0;        // Immediate mode?
  66.  
  67. float rotx = 0.0, roty = 0.0;    // Rotations about x and y per second
  68.  
  69. int paused = 0;
  70.  
  71. int win_width, win_height;
  72.  
  73. const float mouse_poll = 100000;    // How often to poll mouse
  74.  
  75. static int list_names[] = {1, 2, 3, 4, 5, 6};
  76.  
  77. void draw_square();
  78. void define_cube();
  79. void draw_cube();
  80.  
  81. inline unsigned long current_time()
  82. {
  83.   struct timeval time;
  84.   gettimeofday(&time, NULL);
  85.   return (time.tv_sec * 1000000 + time.tv_usec);
  86. }
  87.  
  88. void draw_square()
  89. {
  90.   glPushMatrix();
  91.   if (reload_textures) texmap[1 % n_textures]->specify_texture();
  92.   if (!use_texture) glColor3ub(255, 255, 255);
  93.   square->draw();
  94.   glPopMatrix();
  95. }
  96.  
  97. void define_cube() 
  98. {
  99.  
  100.   glNewList(1, GL_COMPILE);
  101.   glPushMatrix();
  102.   glTranslatef(0, 0, 1.0);
  103.   if (reload_textures) texmap[1 % n_textures]->specify_texture();
  104.   if (!use_texture) glColor3ub(0, 0, 255);
  105.   square->draw();
  106.   glPopMatrix();
  107.   glEndList();
  108.  
  109.   glNewList(2, GL_COMPILE);
  110.   glPushMatrix();
  111.   glRotatef(180, 1, 0, 0);
  112.   glTranslatef(0, 0, 1.0);
  113.   if (reload_textures) texmap[6 % n_textures]->specify_texture();
  114.   if (!use_texture) glColor3ub(0, 0, 255);
  115.   square->draw();
  116.   glPopMatrix();
  117.   glEndList();
  118.  
  119.   glNewList(3, GL_COMPILE);
  120.   glPushMatrix();
  121.   glRotatef(90, 0, 1.0, 0);
  122.   glTranslatef(0, 0, 1.0);
  123.   if (reload_textures) texmap[2 % n_textures]->specify_texture();
  124.   if (!use_texture) glColor3ub(255, 0, 0);
  125.   square->draw();
  126.   glPopMatrix();
  127.   glEndList();
  128.  
  129.   glNewList(4, GL_COMPILE);
  130.   glPushMatrix();
  131.   glRotatef(-90, 0, 1.0, 0);
  132.   glTranslatef(0, 0, 1.0);
  133.   if (reload_textures) texmap[5 % n_textures]->specify_texture();
  134.   if (!use_texture) glColor3ub(255, 0, 0);
  135.   square->draw();
  136.   glPopMatrix();
  137.   glEndList();
  138.  
  139.   glNewList(5, GL_COMPILE);
  140.   glPushMatrix();
  141.   glRotatef(90, 1.0, 0.0, 0);
  142.   glTranslatef(0, 0, 1.0);
  143.   if (reload_textures) texmap[3 % n_textures]->specify_texture();
  144.   if (!use_texture) glColor3ub(0, 255, 0);
  145.   square->draw();
  146.   glPopMatrix();
  147.   glEndList();
  148.  
  149.   glNewList(6, GL_COMPILE);
  150.   glPushMatrix();
  151.   glRotatef(-90, 1.0, 0.0, 0);
  152.   glTranslatef(0, 0, 1.0);
  153.   if (reload_textures) texmap[4 % n_textures]->specify_texture();
  154.   if (!use_texture) glColor3ub(0, 255, 0);
  155.   square->draw();
  156.   glPopMatrix();
  157.   glEndList();
  158. }
  159.  
  160. void call_cube() 
  161. {
  162.   glCallLists(6, GL_INT, list_names);
  163. }
  164.  
  165. void draw_cube()
  166. {
  167.   {
  168.     glPushMatrix();
  169.     glTranslatef(0, 0, 1.0);
  170.     if (reload_textures) texmap[1 % n_textures]->specify_texture();
  171.     if (!use_texture) glColor3ub(0, 0, 255);
  172.     square->draw();
  173.     glPopMatrix();
  174.   } 
  175.   {
  176.     glPushMatrix();
  177.     glRotatef(180, 1, 0, 0);
  178.     glTranslatef(0, 0, 1.0);
  179.     if (reload_textures) texmap[6 % n_textures]->specify_texture();
  180.     if (!use_texture) glColor3ub(0, 0, 255);
  181.     square->draw();
  182.     glPopMatrix();
  183.   } 
  184.   {
  185.     glPushMatrix();
  186.     glRotatef(90, 0, 1.0, 0);
  187.     glTranslatef(0, 0, 1.0);
  188.     if (reload_textures) texmap[2 % n_textures]->specify_texture();
  189.     if (!use_texture) glColor3ub(255, 0, 0);
  190.     square->draw();
  191.     glPopMatrix();
  192.   }
  193.   {
  194.     glPushMatrix();
  195.     glRotatef(-90, 0, 1.0, 0);
  196.     glTranslatef(0, 0, 1.0);
  197.     if (reload_textures) texmap[5 % n_textures]->specify_texture();
  198.     if (!use_texture) glColor3ub(255, 0, 0);
  199.     square->draw();
  200.     glPopMatrix();
  201.   } 
  202.   {
  203.     glPushMatrix();
  204.     glRotatef(90, 1.0, 0.0, 0);
  205.     glTranslatef(0, 0, 1.0);
  206.     if (reload_textures) texmap[3 % n_textures]->specify_texture();
  207.     if (!use_texture) glColor3ub(0, 255, 0);
  208.     square->draw();
  209.     glPopMatrix();
  210.   }
  211.   {
  212.     glPushMatrix();
  213.     glRotatef(-90, 1.0, 0.0, 0);
  214.     glTranslatef(0, 0, 1.0);
  215.     if (reload_textures) texmap[4 % n_textures]->specify_texture();
  216.     if (!use_texture) glColor3ub(0, 255, 0);
  217.     square->draw();
  218.     glPopMatrix();
  219.   } 
  220. }
  221.  
  222. void do_rotation(unsigned long last_time, unsigned long time)
  223. {
  224.   float elapsed_time;
  225.  
  226.   elapsed_time = (time - last_time) / 1000000.0;
  227.  
  228.   glPushMatrix(); 
  229.   glLoadIdentity(); 
  230.   if (!paused) {
  231.     glRotatef(elapsed_time * rotx, 1, 0, 0);
  232.     glRotatef(elapsed_time * roty, 0, 1, 0);
  233.   }
  234.   glMultMatrixf(matrix);
  235.   glGetFloatv(GL_MODELVIEW_MATRIX, matrix);
  236.   glPopMatrix(); 
  237.   glMultMatrixf(matrix);
  238. }
  239.  
  240. unsigned long draw(unsigned long last_draw)
  241. {
  242.   unsigned long time = current_time();
  243.  
  244.   glMatrixMode(GL_PROJECTION);
  245.   glLoadIdentity();
  246.   gluPerspective (45.0, 1.0, 0.01, 20.0); 
  247.  
  248.   glMatrixMode(GL_MODELVIEW);
  249.   glLoadIdentity();
  250.   glTranslatef(0, 0, -5);
  251.  
  252.   glClear(GL_COLOR_BUFFER_BIT);
  253.  
  254.   glColor4ub(255, 255, 255, 255);
  255.   if (use_texture) glEnable(GL_TEXTURE_2D);
  256.  
  257.   glPushMatrix();
  258.  
  259.   do_rotation(last_draw, time);
  260.  
  261.   {
  262.     if (transparency) {
  263.       glFrontFace(GL_CW);
  264.       if (cube) 
  265.     if (immediate) draw_cube();
  266.     else call_cube();
  267.       else draw_square();
  268.       glFrontFace(GL_CCW);
  269.     }
  270.     if (cube) 
  271.       if (immediate) draw_cube();
  272.       else call_cube();
  273.     else draw_square(); 
  274.   }
  275.   glPopMatrix();
  276.  
  277.   window->swapbuffers();
  278.  
  279.   return time;
  280. }
  281.  
  282. int mouse_motion(int oldmx, int oldmy, unsigned long last_time,
  283.          int mx, int my, unsigned long time)
  284. {
  285.   float dx, dy, dt;
  286.  
  287.   dt = (time - last_time) / 1000000.0;
  288.  
  289.   // Find the mouse motion vector in screen space
  290.   dx = (float)(mx - oldmx) / (float)win_width;
  291.   dy = (float)(my - oldmy) / (float)win_height;
  292.  
  293.   rotx = dy * 180.0 / dt;
  294.   roty = dx * 180.0 / dt;
  295.  
  296.   if (rotx || roty) return 1;
  297.   else return 0;
  298. }
  299.  
  300. void draw_text(char *string, XFontStruct *f, GLint list)
  301. {
  302.   int i, n = strlen(string), offset = list - f->min_char_or_byte2;
  303.   for (i = 0; i < n; i++) {
  304.     glCallList(string[i] + offset);
  305.     glTranslatef(f->max_bounds.width, 0, 0);
  306.   }
  307. }
  308.  
  309. void draw_initscreen(Display *dpy, int width, int height)
  310. {
  311.   XFontStruct *f;
  312.  
  313.   glClear(GL_COLOR_BUFFER_BIT);
  314.  
  315.   f = XLoadQueryFont(dpy, (char *)default_font);
  316.  
  317.   if (f != NULL) {
  318.     glXUseXFont(f->fid, f->min_char_or_byte2, 
  319.         f->max_char_or_byte2 - f->min_char_or_byte2, 1);
  320.     glMatrixMode(GL_PROJECTION);
  321.     glPushMatrix();
  322.     glLoadIdentity();
  323.     glScalef(2. / (float)width, 2. / (float)height, 1);
  324.     glRasterPos2i(-width / 2 + f->max_bounds.width, 
  325.           (height / 2) - 2. * (f->max_bounds.ascent));
  326.     draw_text("Loading textures...", f, 1);
  327.     glPopMatrix();
  328.     glMatrixMode(GL_MODELVIEW);
  329.   } else printf("Loading textures...\n");
  330.   window->swapbuffers();
  331.  
  332.   if (f != NULL) {
  333.     glDeleteLists(1, f->max_char_or_byte2 - f->min_char_or_byte2);
  334.     XUnloadFont(dpy, f->fid);
  335.   }
  336. }
  337.  
  338. void main(int argc, char **argv)
  339. {
  340.   Display *dpy;
  341.   Window winid;
  342.   XEvent event;
  343.   char buffer[5];
  344.   int bufsize = 5;
  345.   KeySym key;
  346.   XComposeStatus compose;
  347.   int fname;
  348.   GLenum display_type = DEFAULT_DISPLAY_TYPE;
  349.   GLenum display_format = DEFAULT_DISPLAY_FORMAT;
  350.   int alignment = DEFAULT_ALIGNMENT;
  351.   int usign = 0;
  352.   int components = DEFAULT_COMPONENTS;
  353.   int level = DEFAULT_LEVEL;
  354.   GLenum min_filter = GL_LINEAR_MIPMAP_LINEAR;
  355.   GLenum max_filter = GL_LINEAR;
  356.   GLenum environment = DEFAULT_ENVIRONMENT;
  357.   int map_to_alpha = 1;
  358.   int clamp = 1;
  359.   int isize = 512;
  360.   int moving = 1;
  361.   int mx, my, oldmx, oldmy; 
  362.   unsigned long time, last_mouse_time, last_draw = 0.0;
  363.   int button_down = 0;
  364.   Window root_return, child_return;
  365.   int root_x, root_y;
  366.   unsigned int mask_return;
  367.   int i, j;
  368.  
  369.   window = new oglwindow();
  370.   square = new unitsquare();
  371.  
  372.   window->set_title("textured cube");
  373.   window->add_event_mask(ButtonReleaseMask);
  374.   window->set_doublebuffer(1);
  375.   window->open();
  376.  
  377.   square->open();
  378.  
  379.   fname = argc;
  380.   for (i = 1; i < argc; i++) {
  381.     if (argv[i][0] != '-') {
  382.       fname = i;
  383.       break;
  384.     }
  385.     switch(argv[i][1]) {
  386.     case 'a':            // Alignment
  387.       alignment = atoi(&argv[i][2]);
  388.       break;
  389.     case 'C':            // Clamping
  390.       clamp = atoi(&argv[i][2]);
  391.       break;
  392.     case 'c':            // Components
  393.       components = atoi(&argv[i][2]);
  394.       break;
  395.     case 'e':            // Texture environment
  396.       switch(argv[i][2]) {
  397.       case 'm':
  398.     environment = GL_MODULATE;
  399.     break;
  400.       case 'd':
  401.     environment = GL_DECAL;
  402.     break;
  403.       case 'b':
  404.     environment = GL_BLEND;
  405.     break;
  406.       }
  407.       break;
  408.     case 'f':            // Format
  409.       if (!strcmp(argv[i]+2, "r")) display_format = GL_RED;
  410.       else if (!strcmp(argv[i]+2, "g")) display_format = GL_GREEN;
  411.       else if (!strcmp(argv[i]+2, "b")) display_format = GL_BLUE;
  412.       else if (!strcmp(argv[i]+2, "a")) display_format = GL_ALPHA;
  413.       else if (!strcmp(argv[i]+2, "rgb")) display_format = GL_RGB;
  414.       else if (!strcmp(argv[i]+2, "rgba")) display_format = GL_RGBA;
  415.       else if (!strcmp(argv[i]+2, "l")) display_format = GL_LUMINANCE;
  416.       else if (!strcmp(argv[i]+2, "la")) display_format = 
  417.     GL_LUMINANCE_ALPHA;
  418.       else fprintf(stderr, "Unrecognized display format option %s.\n",
  419.            argv[i]);      
  420.       break;
  421.     case 'I':            // Immediate Mode? 
  422.       immediate = atoi(argv[i]+2);
  423.       break;
  424.     case 'i':            // Minimize filter
  425.       if (!strcmp(argv[i]+2, "n")) min_filter = GL_NEAREST;
  426.       else if (!strcmp(argv[i]+2, "l")) min_filter = GL_LINEAR;
  427.       else if (!strcmp(argv[i]+2, "nmn")) min_filter = 
  428.     GL_NEAREST_MIPMAP_NEAREST;
  429.       else if (!strcmp(argv[i]+2, "lmn")) min_filter =
  430.     GL_LINEAR_MIPMAP_NEAREST;
  431.       else if (!strcmp(argv[i]+2, "nml")) min_filter =
  432.     GL_NEAREST_MIPMAP_LINEAR;
  433.       else if (!strcmp(argv[i]+2, "lml")) min_filter =
  434.     GL_LINEAR_MIPMAP_LINEAR;
  435.       else fprintf(stderr, "Unrecognized minimize filter:  %s.\n", argv[i]);
  436.       break;
  437.     case 'l':            // Mipmap reduction level
  438.       level = atoi(&argv[i][2]);
  439.       break;
  440.     case 'm':            // Map luminance to alpha
  441.       map_to_alpha = atoi(&argv[i][2]);
  442.       break;
  443.     case 'n':            // Number of textures
  444.       n_textures = atoi(&argv[i][2]);
  445.       if (n_textures > 1) reload_textures = 1;
  446.       break;
  447.     case 'r':            // Reload textures
  448.       if (argv[i][2] == '0') reload_textures = 0;
  449.       else reload_textures = 1;
  450.       break;
  451.     case 'S':            // Size of image
  452.       isize = atoi(&argv[i][2]);
  453.       break;
  454.     case 't':            // Texture map at all?
  455.       if (argv[i][2] == '0') use_texture = 0;
  456.       else use_texture = 1;
  457.       break;
  458.     case 'u':
  459.       cube = atoi(argv[i]+2);
  460.       break;
  461.     case 'x':            // Maximize filter
  462.       if (!strcmp(argv[i]+2, "n")) max_filter = GL_NEAREST;
  463.       else if (!strcmp(argv[i]+2, "l")) max_filter = GL_LINEAR;
  464.       else fprintf(stderr, "Unrecognized maximize filter:  %s.\n", argv[i]);
  465.       break;
  466.     case 'y':            // Display type;
  467.       if (argv[i][2] == 'u') {
  468.     usign = 1;
  469.     argv[i]++;
  470.       }
  471.       switch(argv[i][2]) {
  472.       case 'b':
  473.     display_type = usign ? GL_UNSIGNED_BYTE : GL_BYTE;
  474.     break;
  475.       case 's':
  476.     display_type = usign ? GL_UNSIGNED_SHORT : GL_SHORT;
  477.     break;
  478.       case 'i':
  479.     display_type = usign ? GL_UNSIGNED_INT : GL_INT;
  480.     break;
  481.       default:
  482.     fprintf(stderr, "Unrecognized display type option %s.\n",
  483.         argv[i]);
  484.     break;
  485.       }
  486.       break;
  487.     case 'h':
  488.     default:
  489.       fprintf(stderr, "Usage:\n");
  490.       fprintf(stderr, "tex_test [-t{0}] [file1.rgb file2.rgb...]\n");
  491.       exit(1);
  492.     }
  493.   }
  494.  
  495.   window->map();
  496.   window->winset();
  497.  
  498.   dpy = window->get_display();
  499.   winid = window->get_window();
  500.   win_width = window->get_width();
  501.   win_height = window->get_height();
  502.  
  503.   draw_initscreen(dpy, win_width, win_height);
  504.  
  505.   if (use_texture) {
  506.     if (argc - fname > n_textures) n_textures = argc - fname;
  507.     if (argc - fname == 0) {
  508.       fname = argc - 1;
  509.       argv[fname] = default_image;
  510.     }
  511.     texmap = (texture **)malloc(n_textures * sizeof(texture *));
  512.     for (i = 0; i < n_textures; i++) {
  513.       
  514.       texmap[i] = new texture();
  515.       texmap[i]->open();
  516.       
  517.       if (fname < argc) texmap[i]->create_from_file(argv[fname++]);
  518.       else 
  519.     if (i % 2) 
  520.       texmap[i]->create_diag_stripes(isize, (int)(pow(2.0, 6.0 - 1.0)),
  521.                      1.0 * (float)((i+1)%2), 
  522.                      0.5 * (float)((i+1)%3), 
  523.                      .33 * (float)((i+1)%4), 1.0, 1.0,
  524.                      .33 * (float)(i%4), 
  525.                      0.5 * (float)(i%3), 
  526.                      1.0 * (float)(i%2), 1.0, 1.0);
  527.     else 
  528.       texmap[i]->create_checkerboard(isize, (int)(pow(2.0, 6.0)),
  529.                      1.0 * (float)((i+1)%2), 
  530.                      0.5 * (float)((i+1)%3), 
  531.                      .33 * (float)((i+1)%4), 1.0, 1.0,
  532.                      .33 * (float)((i+1)%4), 
  533.                      0.5 * (float)((i+1)%3), 
  534.                      1.0 * (float)((i+1)%2), 1.0, 1.0); 
  535.       if (map_to_alpha) texmap[i]->map_lum_to_alpha();
  536.     }
  537.   }
  538.  
  539.   // Now do everything that requires a graphics context
  540.   moving = 0;
  541.  
  542.   glMatrixMode(GL_MODELVIEW);
  543.   glLoadIdentity();
  544.   glGetFloatv(GL_MODELVIEW_MATRIX, matrix);
  545.   
  546.   if (use_texture) {
  547.     for (i = 0; i < n_textures; i++) {
  548.       texmap[i]->set_display_type(display_type);
  549.       texmap[i]->set_display_format(display_format);
  550.       texmap[i]->set_alignment(alignment);
  551.       texmap[i]->set_components(components);
  552.       texmap[i]->set_level(level);
  553.       
  554.       texmap[i]->set_min_filter(min_filter);
  555.       texmap[i]->set_max_filter(max_filter);
  556.       
  557.       texmap[i]->set_environment(environment);
  558.     }
  559.     texmap[0]->specify_texture();
  560.   }
  561.  
  562.  
  563.   if (map_to_alpha && use_texture) {
  564.     glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  565.     glEnable(GL_BLEND);
  566.     transparency = 1;
  567.   } 
  568.  
  569.   glEnable(GL_CULL_FACE);
  570.   if (clamp) {
  571.     j = GL_CLAMP;
  572.     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
  573.     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
  574.   }
  575.  
  576.   if (!immediate) {
  577.     define_cube();
  578.     if (use_texture) 
  579.       for (i = 0; i < n_textures; i++) texmap[i]->pixels_free();
  580.   }
  581.  
  582.   while (1) {
  583.     while(((moving || button_down) && XPending(dpy)) || 
  584.       (moving == 0 && button_down == 0)) {
  585.       XNextEvent(dpy, &event);
  586.       switch(event.type) {
  587.       case Expose:
  588.     last_draw = draw(last_draw);
  589.     break;
  590.       case ConfigureNotify:
  591.     window->resize();
  592.     win_width = window->get_width();
  593.     win_height = window->get_height();
  594.     break;
  595.       case ButtonPress:
  596.     button_down = 1;
  597.     oldmx = event.xbutton.x;
  598.     oldmy = event.xbutton.y;
  599.     last_mouse_time = current_time();
  600.     break;
  601.       case ButtonRelease:
  602.     button_down = 0;
  603.     break;
  604.       case KeyPress:
  605.     XLookupString(&event.xkey, buffer, bufsize, &key, &compose);
  606.     if (key == XK_Escape) exit(0);
  607.     else if (key == XK_h || key == XK_H) {
  608.       rotx = roty = 0.0;
  609.       moving = 0;
  610.       paused = 0;
  611.       last_draw = draw(last_draw);
  612.     }
  613.     else if (key == XK_w || key == XK_W) {
  614.       rotx = roty = 0.0;
  615.       glPushMatrix();
  616.       glLoadIdentity();
  617.       glGetFloatv(GL_MODELVIEW_MATRIX, matrix);
  618.       glPopMatrix();
  619.       moving = 0;
  620.       paused = 0;
  621.       last_draw = draw(last_draw);
  622.     }
  623.     else if (key == XK_space) paused = ~paused;
  624.     break;
  625.       }
  626.     }
  627.     if (moving) time = last_draw = draw(last_draw);
  628.     else time = current_time();
  629.     if (button_down && time - last_mouse_time > mouse_poll) {
  630.       XQueryPointer(dpy, winid, &root_return, &child_return, &root_x,
  631.             &root_y, &mx, &my, &mask_return);
  632.       moving = mouse_motion(oldmx, oldmy, last_mouse_time, mx, my, time);
  633.       oldmx = mx;
  634.       oldmy = my;
  635.       last_mouse_time = time;
  636.     }
  637.   }
  638.  
  639. }
  640.  
  641.  
  642.